<?php

namespace App\V3\V3_1\Services;

use App\V3\V3_1\Models\InStorageLogModel;
use App\V3\V3_1\Models\LoginModel;
use App\V3\V3_1\Models\LogInStorageModel;
use App\V3\V3_1\Models\LogOutPackageModel;
use App\V3\V3_1\Models\LogOutStorageModel;
use App\V3\V3_1\Models\LogPackageContentModel;
use App\V3\V3_1\Models\LogPackageModel;
use App\V3\V3_1\Models\MaterielModel;
use App\V3\V3_1\Models\ProductOrderModel;
use App\V3\V3_1\Models\SalesReturnModel;
use App\V3\V3_1\Models\SellModel;
use App\V3\V3_1\Models\SerialNumberModel;
use App\V3\V3_1\Models\StorageBatchModel;
use App\V3\V3_1\Models\StorageManageModel;
use App\V3\V3_1\Models\StorageModel;
use App\V3\V3_1\Models\UserModel;
use Exception;
use Illuminate\Support\Facades\DB;
use App\V3\V3_1\Models\MaterielSerialNumberModel;
use Illuminate\Support\Facades\Log;

class LogService
{
    //操作记录详细
    static public function detail($data)
    {
        switch($data['type']) {
            case 0:
                $result = self::logInstorageDetail($data);
                break;
            case 1:
                $result = self::logOutstorageDetail($data);
                break;
            case 2:
                $result = self::logPackageContentDetail($data);
                break;
        }

        /* if(!empty($result['is_use_serial'])){

            if($result['is_use_serial'] == 1){
                $condition['type_id']=$result['type_id'];
                $condition['materiel_content_id']=$result['id'];

                $info = MaterielSerialNumberModel::select('serial_no')->where($condition)->first();

                $result['serial_number_list']=[];

                if(!empty($info['serial_no'])){

                    $result['serial_number_list'] = explode(',', $info['serial_no']);
                }
            }
        }

        if(!empty($result['content']['is_use_serial'])){

            if($result['content']['is_use_serial'] == 1){
                MaterielSerialNumberModel::where()->first();
            }
        } */

        return $result;

    }

    static private function logInstorageDetail($data)
    {
        $info = LogInstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name as last_storage_name',
            'f.storage_address as last_storage_address',
            'e.storage_name',
            'e.storage_address',
//            'a.materiel_class_name',
//            'a.materiel_class_no',
            'g.materiel_name',
            'g.type_name',
            'g.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.all_id_type',
            'a.all_id',
            'a.remark',
            'a.is_cancel',
            'a.in_storage_time',
            'a.purchase_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.class_name',
            'c.class_no',
            'd.username',
            'd.nickname',
            'g.is_use_serial',
            'serial_number',
            'i.batch_no'
        )
            ->from('log_instorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.last_storage_id')
            ->leftJoin('materiel_type as g', 'g.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage_batch as i','i.id','=','a.batch_id')
            ->where([
                'a.id' => $data['id'],
            ])
            ->first();

            if(!empty($info['serial_number'])){
                $info['serial_number'] = array_filter(explode(',', $info['serial_number']), function($v) { return $v !== ''; });

            }else{
                $info['serial_number'] = [];
            }

            switch($info['all_id_type']) {
                case 0://无
                case 1://报溢
                case 6://组件返仓
                    $info['order_no'] = '';
                    break;
                case 2://退货
                    $salesReturnInfo = SalesReturnModel::where('id', $info['all_id'])->first();
                    $info['order_no'] = $salesReturnInfo['order_no'];
                    break;
                case 3://采购
                    $materielInfo = MaterielModel::where('id', $info['all_id'])->first();
                    $info['order_no'] = $materielInfo['order_no'];
                    break;
                case 4://生产订单
                    $productOrderInfo = ProductOrderModel::where('id', $info['all_id'])->first();
                    $info['order_no'] = $productOrderInfo['product_no'];
                    break;
            }

            return $info;
    }

    //出库操作记录详细
    static private function logOutstorageDetail($data)
    {
         $info = LogOutstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name as next_storage_name',
            'f.storage_address as next_storage_address',
            'e.storage_name',
            'e.storage_address',
            'a.materiel_type_id as goods_id',
//                'a.materiel_class_no',
            'g.materiel_name',
            'g.type_name',
            'g.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.remark',
            'a.all_id_type',
            'a.all_id',
            'a.is_cancel',
            'a.out_storage_time',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.class_name',
            'c.class_no',
            'd.username',
            'd.nickname',
            'g.is_use_serial',
            'a.serial_number',
            'i.batch_no',
             'a.shelf_id as sh_id',
             'a.location_id as lo_id',
             'a.out_storage_time'
        )
            ->from('log_outstorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.next_storage_id')
            ->leftJoin('materiel_type as g', 'g.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage_batch as i','i.id','=','a.storage_batch_id')
            ->where([
                'a.id' => $data['id']
            ])
            ->first();

           if(!empty($info['serial_number'])){
                $loCondition= [];
                $serialArr = [];
                $loCondition['shelf_id'] = $info['sh_id'];
                $loCondition['location_id'] = $info['lo_id'];
                $loCondition['out_storage_time'] = strtotime($info['out_storage_time']);
                $loCondition['materiel_type_id'] = $info['goods_id'];
                $loList = LogOutstorageModel::select('serial_number')->where($loCondition)->get()->toArray();

                if(!empty($loList)){
                    foreach($loList as $key=>$val){
                        if(!empty($val['serial_number'])){
                            $serialData = explode(',', $val['serial_number']);
                            if(is_array($serialData)){
                                foreach($serialData as $sKey=>$sVal){
                                    if(!empty($sVal)){
                                        $serialArr[] = $sVal;
                                    }
                                }
                            }else{
                                $serialArr[] = $val['serial_number'];
                            }
                        }
                    }
                }
                $info['serial_number'] = $serialArr;
            }else{
                $info['serial_number'] = [];
            }

        switch($info['all_id_type']) {
            case 0://无
            case 1://报损
                $info['order_no'] = '';
                break;
            case 2://销售
                $sellInfo = SellModel::where('id', $info['all_id'])->first();
                $info['order_no'] = $sellInfo['order_no'];
                break;
            case 3://生产订单
                $productOrderInfo = ProductOrderModel::where('id', $info['all_id'])->first();
                $info['order_no'] = $productOrderInfo['product_no'];
                break;
        }

            return $info;
    }

    //套餐出库记录详细
    static public function logPackageContentDetail($data)
    {
        $datas = LogPackageModel::select(
            'a.id',
            'c.package_name',
            'num',
            'remark',
            'a.all_id_type',
            'a.all_id',
            'a.created_at',
            'username',
            'nickname',
            'is_cancel',
            'a.remark'
        )
            ->from('log_package as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('hasManyContent', function($query) {
                $query->select(
                    'log_package_content.id',
                    'log_package_id',
                    'a.storage_name',
                    'a.storage_address',
                    'b.class_name as second_class_name',
                    'c.class_name as first_class_name',
                    'd.materiel_name',
                    'd.type_name',
                    'operate_num',
                    'e.in_storage_num',
                    'd.is_use_serial',
                    'log_package_content.serial_number',
                    'i.batch_no'
                )
                    ->leftJoin('storage as a', 'a.id', '=', 'log_package_content.storage_id')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'log_package_content.materiel_class_id')
                    ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'log_package_content.materiel_type_id')
                    ->leftJoin('storage_manage as e', 'e.id', '=', 'log_package_content.out_storage_manage_id')
                    ->leftJoin('storage_batch as i','i.id','=','log_package_content.storage_batch_id');
            })
            ->leftJoin('package as c', 'c.id', '=', 'a.package_id')
            ->where('a.id', $data['id'])
            ->get()->toArray();
            if(!empty($datas[0]['has_many_content'])){
                foreach ($datas[0]['has_many_content'] as &$v){
                    if(!empty($v['serial_number'])){
                        $v['serial_number'] = explode(',', $v['serial_number']);
                    }else{
                        $v['serial_number']=[];
                    }
                }
            }
        $arr['id'] = $datas[0]['id'];
        $arr['package_name'] = $datas[0]['package_name'];
        $arr['num'] = $datas[0]['num'];
        $arr['remark'] = $datas[0]['remark'];
        $arr['created_at'] = $datas[0]['created_at'];
        $arr['username'] = $datas[0]['username'];
        $arr['nickname'] = $datas[0]['nickname'];
        $arr['is_cancel'] = $datas[0]['is_cancel'];
        $arr['content'] = $datas[0]['has_many_content'];

        switch($arr['all_id_type']) {
            case 0://无
            case 1://报损
                $info['order_no'] = '';
                break;
            case 2://销售
                $sellInfo = SellModel::where('id', $arr['all_id'])->first();
                $info['order_no'] = $sellInfo['order_no'];
                break;
            case 3://退货
                $salesReturnInfo = SalesReturnModel::where('id', $arr['all_id'])->first();
                $info['order_no'] = $salesReturnInfo['order_no'];
                break;
        }

        return $arr;
    }


    static public function logDel($data, $logIdArr, $condition)
    {
        switch($data['type']) {
            //入库
            case 0:
                $result = self::instorageDel($logIdArr, $condition);
                break;
            //出库
            case 1:
                $result = self::outstorageDel($logIdArr, $condition);
                break;
            //套餐出库
            case 2:
                $result = self::packageOutstorageDel($logIdArr, $condition);
                break;
        }

        return $result;
    }

    static private function instorageDel($logIdArr, $condition)
    {

        foreach($logIdArr as $value) {
            $logInfo = LogInstorageModel::where([
                'id' => $value,
                'delete_flag' => 0
            ])
                ->where($condition)
                ->first();

            if(empty($logInfo)) {
                return ['code' => 1, 'msg' => '目标日志不存在,请重试', 'data' => ''];
            }

            if(!$logInfo['is_cancel']) {
                return ['code' => 1, 'msg' => '目标日志未撤销，不可删除', 'data' => ''];
            }
        }

        LogInstorageModel::whereIn('id', $logIdArr)->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static private function outstorageDel($logIdArr, $condition)
    {
        foreach($logIdArr as $value) {
            $logInfo = LogOutstorageModel::where([
                'id' => $value,
                'delete_flag' => 0
            ])
                ->where($condition)
                ->first();

            if(empty($logInfo)) {
                return ['code' => 1, 'msg' => '目标日志不存在,请重试', 'data' => ''];
            }

            if(!$logInfo['is_cancel']) {
                return ['code' => 1, 'msg' => '目标日志未撤销，不可删除', 'data' => ''];
            }
        }

        LogOutstorageModel::whereIn('id', $logIdArr)->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static private function packageOutstorageDel($logIdArr, $condition)
    {
        foreach($logIdArr as $value) {
            $logInfo = LogPackageModel::where([
                'id' => $value,
                'delete_flag' => 0
            ])
                ->where($condition)
                ->first();

            if(empty($logInfo)) {
                return ['code' => 1, 'msg' => '目标日志不存在,请重试', 'data' => ''];
            }

            if(!$logInfo['is_cancel']) {
                return ['code' => 1, 'msg' => '目标日志未撤销，不可删除', 'data' => ''];
            }
        }

        LogPackageModel::whereIn('id', $logIdArr)->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }


    //操作记录列表
    static public function list($data)
    {
        //DB::enableQueryLog();
        switch($data['type']) {
            //入库
            case 0:
                $result = self::instorageList($data);
                break;
                //出库
            case 1:
                $result = self::outstorageList($data);
                break;
                //套餐出库
            case 2:
                $result = self::packageOutstorageList($data);
                break;
        }
        // $sql = DB::getQueryLog();
        //var_dump($sql);die;
        return $result;
    }

    //入库操作记录
    static private function instorageList($data)
    {
        $operateCondition = [];
        if($data['user_id'] == $data['main_id']) {
            $operateCondition['main_id'] = ['EQ' => $data['main_id']];
        }
        else {
            if($data['is_share_log']) {
                $operateCondition['main_id'] = ['EQ' => $data['main_id']];
            }
            else {
                $operateCondition['user_id'] = ['EQ' => $data['user_id']];
            }
        }

        //根据是否共享操作记录找到对应的库存信息id
        $operateSearchLogStorageData = LogInstorageModel::select('id')->where($operateCondition)->get()->toArray();

        $logId = [];
        if(!empty($operateSearchLogStorageData)) {
            foreach($operateSearchLogStorageData as $val) {
                $logId[] = $val['id'];
            }
        }

//        if($data['is_share_storage']) {
            $storageInfo = StorageModel::select('id')->where('user_id', $data['user_id'])->get()->toArray();

            $storageId = [];
            foreach($storageInfo as $value) {
                $storageId[] = $value['id'];
            }

            //仓库共享开启后，获取自己所负责的仓库信息用于查找他人操作我的仓库的进出库记录-普通入库
            $storageSearchLogStorageData = LogInstorageModel::select('id')->whereIn('storage_id', $storageId)->get()->toArray();
            //仓库共享开启后，获取自己所负责的仓库信息用于查找他人操作我的仓库的进出库记录-调拨操作
            $allocateSearchLogStorageData = LogInstorageModel::select('id')->whereIn('last_storage_id', $storageId)->get()->toArray();

            if(!empty($storageSearchLogStorageData)) {
                foreach($storageSearchLogStorageData as $v1) {
                    if(!in_array($v1['id'], $logId)) {
                        $logId[] = $v1['id'];
                    }
                }
            }

            if(!empty($allocateSearchLogStorageData)) {
                foreach($allocateSearchLogStorageData as $v2) {
                    if(!in_array($v2['id'], $logId)) {
                        $logId[] = $v2['id'];
                    }
                }
            }
//        }

        $query = LogInstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name',
            'f.storage_address',
            'g.storage_name as last_storage_name',
            'g.storage_address as last_storage_address',
            //            'a.materiel_class_name',
        //            'a.materiel_class_no',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.remark',
            'a.is_cancel',
            'a.in_storage_time',
            'a.purchase_no',
            'c.class_name',
            'c.class_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'd.username',
            'd.nickname',
            'h.location_name',
            'i.shelf_name',
            'a.serial_number'
            )
            ->from('log_instorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.storage_id')
            ->leftJoin('storage as g', 'g.id', '=', 'a.last_storage_id')
            ->leftJoin('storage_shelf_location as h','h.id','=','a.location_id')
            ->leftJoin('storage_shelf as i','i.id','=','a.shelf_id')
            ->where('a.delete_flag', 0)
            ->where('a.is_cancel', $data['status']);

            if($data['materiel_class_id'] != 0) {
                $query->where('a.materiel_class_id', $data['materiel_class_id']);
            }

            $keyword = empty($data['keyword'])?'':$data['keyword'];

            if(!empty($data['start_time'])) {
                $startTimeArr = explode(' ', $data['start_time']);
                $startTime = strtotime($startTimeArr[0].' 00:00:00');
            }

            if(!empty($data['end_time'])) {
                $endTimeArr = explode(' ', $data['end_time']);
                $endTime = strtotime($endTimeArr[0].' 23:59:59');
            }

            if(!empty($startTime) && !empty($endTime)) {
                $query->whereBetween('in_storage_time', [$startTime, $endTime]);
            }
            else if(!empty($startTime) && empty($endTime)) {
                $query->where('in_storage_time', '>=', $startTime);
            }
            else if(empty($startTime) && !empty($endTime)) {
                $query->where('in_storage_time', '<=', $endTime);
            }

            return $query->where(function($query) use ($keyword, $data) {
                $query->orWhere('b.class_name', 'like', '%'.$keyword.'%');
                $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
                $query->orWhere('c.class_name', 'like', '%'.$keyword.'%');
                $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
                $query->orWhere('e.materiel_name', 'like', '%'.$keyword.'%');
                $query->orWhere('e.type_name', 'like', '%'.$keyword.'%');
                $query->orWhere('e.materiel_no', 'like', '%'.$keyword.'%');
                $query->orWhere('f.storage_name', 'like', '%'.$keyword.'%');
                $query->orWhere('g.storage_name', 'like', '%'.$keyword.'%');

                if($data['type'] == 0) {
                    $query->orWhere('purchase_no', 'like', '%'.$keyword.'%');
                }
            })
                ->whereIn('a.id', $logId)
            ->orderBy('a.id', 'desc')
            ->paginate($data['pageSize'],['*'], '',$data['currentPage'])->toArray();
    }

    //出库操作记录
    static private function outstorageList($data)
    {
        $operateCondition = [];
        if($data['user_id'] == $data['main_id']) {
            $operateCondition['main_id'] = ['EQ' => $data['main_id']];
        }
        else {
            if($data['is_share_log']) {
                $operateCondition['main_id'] = ['EQ' => $data['main_id']];
            }
            else {
                $operateCondition['user_id'] = ['EQ' => $data['user_id']];
            }
        }

        //根据是否共享操作记录找到对应的出库信息id
        $operateSearchLogStorageData = LogOutstorageModel::select('id')->where($operateCondition)->get()->toArray();

        $logId = [];
        if(!empty($operateSearchLogStorageData)) {
            foreach($operateSearchLogStorageData as $val) {
                $logId[] = $val['id'];
            }
        }

//        if($data['is_share_storage']) {
            $storageInfo = StorageModel::select('id')->where('user_id', $data['user_id'])->get()->toArray();

            $storageId = [];
            foreach($storageInfo as $value) {
                $storageId[] = $value['id'];
            }

            //仓库共享开启后，获取自己所负责的仓库信息用于查找他人操作我的仓库的进出库记录-普通入库
            $storageSearchLogStorageData = LogOutstorageModel::select('id')->whereIn('storage_id', $storageId)->get()->toArray();
            //仓库共享开启后，获取自己所负责的仓库信息用于查找他人操作我的仓库的进出库记录-调拨操作
            $allocateSearchLogStorageData = LogOutstorageModel::select('id')->whereIn('next_storage_id', $storageId)->get()->toArray();

            if(!empty($storageSearchLogStorageData)) {
                foreach($storageSearchLogStorageData as $v1) {
                    if(!in_array($v1['id'], $logId)) {
                        $logId[] = $v1['id'];
                    }
                }
            }

            if(!empty($allocateSearchLogStorageData)) {
                foreach($allocateSearchLogStorageData as $v2) {
                    if(!in_array($v2['id'], $logId)) {
                        $logId[] = $v2['id'];
                    }
                }
            }
//        }

        DB::enableQueryLog();
        $query = LogOutstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name',
            'f.storage_address',
            'g.storage_name as next_storage_name',
            'g.storage_address as next_storage_address',
            //            'a.materiel_class_name',
        //            'a.materiel_class_no',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.remark',
            'a.is_cancel',
            'a.out_storage_time',
            'c.class_name',
            'c.class_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'd.username',
            'd.nickname',
            'h.location_name',
            'i.shelf_name',
            'a.serial_number'
            )
            ->from('log_outstorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.storage_id')
            ->leftJoin('storage as g', 'g.id', '=', 'a.next_storage_id')
            ->leftJoin('storage_shelf_location as h','h.id','=','a.location_id')
            ->leftJoin('storage_shelf as i','i.id','=','a.shelf_id')
            ->where('a.delete_flag', 0)
            ->where('is_cancel', $data['status']);

            if($data['materiel_class_id'] != 0) {
                $query->where('a.materiel_class_id', $data['materiel_class_id']);
            }

            $keyword = empty($data['keyword'])?'':$data['keyword'];

            if(!empty($data['start_time'])) {
                $startTimeArr = explode(' ', $data['start_time']);
                $startTime = strtotime($startTimeArr[0].' 00:00:00');
            }

            if(!empty($data['end_time'])) {
                $endTimeArr = explode(' ', $data['end_time']);
                $endTime = strtotime($endTimeArr[0].' 23:59:59');
            }

            if(!empty($startTime) && !empty($endTime)) {
                $query->whereBetween('out_storage_time', [$startTime, $endTime]);
            }
            else if(!empty($startTime) && empty($endTime)) {
                $query->where('out_storage_time', '>=', $startTime);
            }
            else if(empty($startTime) && !empty($endTime)) {
                $query->where('out_storage_time', '<=', $endTime);
            }

            return  $query->where(function($query) use ($keyword, $data) {
                $query->orWhere('b.class_name', 'like', '%'.$keyword.'%');
                $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
                $query->orWhere('c.class_name', 'like', '%'.$keyword.'%');
                $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
                $query->orWhere('e.materiel_name', 'like', '%'.$keyword.'%');
                $query->orWhere('e.type_name', 'like', '%'.$keyword.'%');
                $query->orWhere('e.materiel_no', 'like', '%'.$keyword.'%');
                $query->orWhere('f.storage_name', 'like', '%'.$keyword.'%');
                $query->orWhere('g.storage_name', 'like', '%'.$keyword.'%');

                if($data['type'] == 0) {
                    $query->orWhere('purchase_no', 'like', '%'.$keyword.'%');
                }
            })
                ->whereIn('a.id', $logId)
//            ->groupBy('out_storage_time')
            ->orderBy('a.id', 'desc')
            ->paginate($data['pageSize'],['*'], '',$data['currentPage'])->toArray();
    }

    static public function packageOutstorageList($data)
    {
        $keyword = empty($data['keyword'])?'':$data['keyword'];

        $operateCondition = [];
        if($data['user_id'] == $data['main_id']) {
            $operateCondition['main_id'] = ['EQ' => $data['main_id']];
        }
        else {
            if($data['is_share_log']) {
                $operateCondition['main_id'] = ['EQ' => $data['main_id']];
            }
            else {
                $operateCondition['user_id'] = ['EQ' => $data['user_id']];
            }
        }

        //根据是否共享操作记录找到对应的出库信息id
        $operateSearchLogStorageData = LogPackageModel::select('id')->where($operateCondition)->get()->toArray();

        $logId = [];
        foreach($operateSearchLogStorageData as $value) {
            $logId[] = $value['id'];
        }

//        if($data['is_share_storage']) {
            $storageInfo = StorageModel::select('id')->where('user_id', $data['user_id'])->get()->toArray();

            $storageId = [];
            foreach($storageInfo as $value) {
                $storageId[] = $value['id'];
            }

            //仓库共享开启后，获取自己所负责的仓库信息用于查找他人操作我的仓库的进出库记录-普通入库
            $storageSearchLogStorageData = LogPackageContentModel::select('log_package_id')->whereIn('storage_id', $storageId)->get()->toArray();

            if(!empty($storageSearchLogStorageData)) {
                foreach($storageSearchLogStorageData as $v1) {
                    if(!in_array($v1['log_package_id'], $logId)) {
                        $logId[] = $v1['log_package_id'];
                    }
                }
            }
//        }

        $query = LogPackageModel::select(
            'a.id',
            'a.package_name',
            'a.num',
            'a.remark',
            'a.is_cancel',
            'a.created_at',
            'username',
            'nickname',
            'd.location_name',
            'e.shelf_name',
            'c.serial_number'
            )
            ->from('log_package as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->leftJoin('log_package_content as c', 'c.log_package_id', '=', 'a.id')
            ->leftJoin('storage_shelf_location as d','d.id','=','c.location_id')
            ->leftJoin('storage_shelf as e','e.id','=','c.shelf_id')
            ->where('a.delete_flag', 0)
            ->where('a.is_cancel', $data['status']);

            if(!empty($data['start_time'])) {
                $startTimeArr = explode(' ', $data['start_time']);
                $startTime = strtotime($startTimeArr[0].' 00:00:00');
            }

            if(!empty($data['end_time'])) {
                $endTimeArr = explode(' ', $data['end_time']);
                $endTime = strtotime($endTimeArr[0].' 23:59:59');
            }

            if(!empty($startTime) && !empty($endTime)) {
                $query->whereBetween('a.created_at', [$startTime, $endTime]);
            }
            else if(!empty($startTime) && empty($endTime)) {
                $query->where('a.created_at', '>=', $startTime);
            }
            else if(empty($startTime) && !empty($endTime)) {
                $query->where('a.created_at', '<=', $endTime);
            }

            $query->where(function($query) use ($keyword) {
                $query->orWhere('package_name', 'like', '%'.$keyword.'%');
                $query->orWhere('materiel_name', 'like', '%'.$keyword.'%');
                $query->orWhere('type_name', 'like', '%'.$keyword.'%');
                $query->orWhere('materiel_no', 'like', '%'.$keyword.'%');
                $query->orWhere('materiel_class_name', 'like', '%'.$keyword.'%');
                $query->orWhere('materiel_class_no', 'like', '%'.$keyword.'%');
            });

                return $query->whereIn('a.id', $logId)->orderBy('a.id', 'desc')
                ->groupBy('a.id')
                ->paginate($data['pageSize'],['*'], '',$data['currentPage'])->toArray();
    }

    static public function cancelAllocateOut($data)
    {
        $info = LogOutStorageModel::where('id', $data['id'])->first();

        if($info['is_cancel']) {
            return ['code' => 1, 'msg' => '当前记录已经撤销，无法重复操作', 'data' => ''];
        }

        DB::beginTransaction();

        try {
            if(!empty($info['serial_number'])) {
                self::cancelSerialAllocateOut($info);
            }
            else {
                if(!empty($info['before_allocate_batch_id'])) {
                    self::cancelBatchAllocateOut($info);
                }
                else {
                    self::cancelNormalAllocateOut($info);
                }
            }

            $info->is_cancel = 1;
            $info->save();

            LogInStorageModel::where('id', $info['log_in_id'])
                ->update([
                    'is_cancel' => 1
                ]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('调拨入库撤销异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static private function cancelNormalAllocateOut($info)
    {
        $outstorageInfo = StorageManageModel::where('id', $info['next_storage_manage_id'])->first();

        if($outstorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($outstorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $outstorageInfo->in_storage_num = $outstorageInfo->in_storage_num - $info['operate_num'];
        $outstorageInfo->virtual_storage_num = $outstorageInfo->virtual_storage_num - $info['operate_num'];
        $outstorageInfo->save();

        StorageManageModel::where('id', $info['curr_storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw('in_storage_num + '.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'delete_flag' => 0
            ]);

        StorageBatchModel::where('id', $info['curr_storage_manage_id'])
            ->update([
                'batch_num' => DB::raw('batch_num + '.$info['operate_num']),
                'batch_left_num' => DB::raw('batch_left_num + '.$info['operate_num']),
            ]);
//
//        LogInStorageModel::where([
//            'type' => 1,
//            'last_storage_manage_id' => $info['curr_storage_manage_id'],
//            'curr_storage_manage_id' => $info['next_storage_address'],
//            'allocate_no' => $info['allocate_no'],
//        ])->update(['is_cancel' => 1]);

        return true;
    }

    static private function cancelBatchAllocateOut($info)
    {
        $outstorageInfo = StorageManageModel::where('id', $info['next_storage_manage_id'])->first();

        if($outstorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($outstorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $outstorageInfo->in_storage_num = $outstorageInfo->in_storage_num - $info['operate_num'];
        $outstorageInfo->virtual_storage_num = $outstorageInfo->virtual_storage_num - $info['operate_num'];
        $outstorageInfo->save();

        StorageManageModel::where('id', $info['curr_storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'delete_flag' => 0
            ]);

        $inBatchInfo = StorageBatchModel::where('id', $info['storage_batch_id'])->first();

        if($inBatchInfo['batch_left_num'] < $info['operate_num']) {
            throw new Exception('调拨后的批次数量不足，无法完成调拨撤销，当前剩余可撤销批次数量为:'.$inBatchInfo['batch_left_num']);
        }

        $inBatchInfo->batch_left_num = $inBatchInfo->batch_left_num - $info['operate_num'];
        $inBatchInfo->batch_num = $inBatchInfo->batch_num - $info['operate_num'];
        $inBatchInfo->save();

        StorageBatchModel::where('id', $info['before_allocate_batch_id'])
            ->update([
                'batch_num' => DB::raw('batch_num + '.$info['operate_num']),
                'batch_left_num' => DB::raw('batch_left_num + '.$info['operate_num']),
            ]);

//        LogInStorageModel::where([
//            'type' => 1,
//            'curr_storage_manage_id' => $info['next_storage_manage_id'],
//            'last_storage_manage_id' => $info['curr_storage_manage_id'],
//            'before_allocate_batch_id' => $info['before_allocate_batch_id'],
//            'storage_batch_id' => $info['batch_id'],
//            'allocate_no' => $info['allocate_no'],
//        ])->update(['is_cancel' => 1]);

        return true;
    }

    static protected function cancelSerialAllocateOut($info)
    {
        $outstorageInfo = StorageManageModel::where('id', $info['next_storage_manage_id'])->first();

        if($outstorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($outstorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $serialNo = array_filter(explode(',', $info['serial_number']), function($v) { return $v !== ''; });
        $outstorageSerialInfo = SerialNumberModel::where([
            'storage_manage_id' => $info['next_storage_manage_id'],
        ])
            ->whereIn('serial_no', $serialNo)
            ->get()->toArray();

        $serialInfo = [];
        foreach($outstorageSerialInfo as $val) {
            if(!$val['status']) {
                throw new Exception('序列号:'.$val['serial_no'].'已被使用，无法撤销');
            }

            $serialInfo[] = [
                'id' => $val['id'],
                'storage_manage_id' => $info['curr_storage_manage_id']
            ];
        }

        if(!empty($serialInfo)) {
            batch()->update(new SerialNumberModel, $serialInfo, 'id');
        }


//        $outstorageSerialInfo = SerialNumberModel::where([
//            'storage_manage_id' => $info['next_storage_manage_id'],
//            'serial_no' => $info['serial_number'],
//        ])->first();
//
//        if($outstorageSerialInfo['status'] == 0) {
//            throw new Exception('序列号:'.$outstorageInfo['serial_no'].'已被使用，无法撤销');
//        }

        $outstorageInfo->in_storage_num = $outstorageInfo->in_storage_num - $info['operate_num'];
        $outstorageInfo->virtual_storage_num = $outstorageInfo->virtual_storage_num - $info['operate_num'];
        $outstorageInfo->save();

//        $outstorageSerialInfo->storage_manage_id = $info['curr_storage_manage_id'];
//        $outstorageSerialInfo->save();

        StorageManageModeL::where([
            'id' => $info['curr_storage_manage_id']
        ])
            ->update([
                'in_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'delete_flag' => 0
            ]);

        return true;
    }

    /**
     * 调拨撤销调入侧
     * @param $data
     * 2022/9/30 17:17
     * Author: Sun Wu
     * @return array
     */
    static public function cancelAllocateIn($data)
    {
        $info = LogInStorageModel::where('id', $data['id'])->first();
//
//        if($info['is_cancel']) {
//            return ['code' => 1, 'msg' => '当前记录已经撤销，无法重复操作', 'data' => ''];
//        }

        DB::beginTransaction();

        try {
            if(!empty($info['serial_number'])) {
                self::cancelSerialAllocateIn($info);
            }
            else {
                if(!empty($info['before_allocate_batch_id'])) {
                    self::cancelBatchAllocateIn($info);
                }
                else {
                    self::cancelNormalAllocateIn($info);
                }
            }

            $info->is_cancel = 1;
            $info->save();

            LogOutStorageModel::where('id', $info['log_out_id'])
                ->update([
                    'is_cancel' => 1
                ]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('调拨入库撤销异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * @throws Exception
     */
    static protected function cancelNormalAllocateIn($info)
    {
        $instorageInfo = StorageManageModel::where('id', $info['curr_storage_manage_id'])->first();

        if($instorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($instorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $instorageInfo->in_storage_num = $instorageInfo->in_storage_num - $info['operate_num'];
        $instorageInfo->virtual_storage_num = $instorageInfo->virtual_storage_num - $info['operate_num'];
        $instorageInfo->save();

        StorageManageModel::where('id', $info['last_storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw('in_storage_num +'.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num +'.$info['operate_num']),
                'delete_flag' => 0
            ]);

        StorageBatchModel::where('id', $info['before_allocate_batch_id'])
            ->update([
                'batch_num' => DB::raw('batch_num + '.$info['operate_num']),
                'batch_left_num' => DB::raw('batch_left_num + '.$info['operate_num']),
            ]);

//        LogOutStorageModel::where([
//            'type' => 1,
//            'curr_storage_manage_id' => $info['last_storage_manage_id'],
//            'next_storage_manage_id' => $info['curr_storage_manage_id'],
//            'allocate_no' => $info['allocate_no'],
//        ])->update(['is_cancel' => 1]);

        return true;
    }

    /**
     * 批次调拨撤销
     * @param $info
     * 2022/9/30 17:08
     * Author: Sun Wu
     * @return bool
     */
    static protected function cancelBatchAllocateIn($info)
    {
        $instorageInfo = StorageManageModel::where('id', $info['curr_storage_manage_id'])->first();

        if($instorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($instorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $instorageInfo->in_storage_num = $instorageInfo->in_storage_num - $info['operate_num'];
        $instorageInfo->virtual_storage_num = $instorageInfo->virtual_storage_num - $info['operate_num'];
        $instorageInfo->save();

        StorageManageModel::where('id', $info['last_storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'delete_flag' => 0
            ]);

        $inBatchInfo = StorageBatchModel::where('id', $info['batch_id'])->first();

        if($inBatchInfo['batch_left_num'] < $info['operate_num']) {
            throw new Exception('调拨后的批次数量不足，无法完成调拨撤销，当前剩余可撤销批次数量为:'.$inBatchInfo['batch_left_num']);
        }

        $inBatchInfo->batch_left_num = $inBatchInfo->batch_left_num - $info['operate_num'];
        $inBatchInfo->batch_num = $inBatchInfo->batch_num - $info['operate_num'];
        $inBatchInfo->save();

        StorageBatchModel::where('id', $info['before_allocate_batch_id'])
            ->update([
                'batch_num' => DB::raw('batch_num + '.$info['operate_num']),
                'batch_left_num' => DB::raw('batch_left_num + '.$info['operate_num']),
            ]);

//        LogOutStorageModel::where([
//            'type' => 1,
//            'curr_storage_manage_id' => $info['last_storage_manage_id'],
//            'next_storage_manage_id' => $info['curr_storage_manage_id'],
//            'before_allocate_batch_id' => $info['before_allocate_batch_id'],
//            'storage_batch_id' => $info['batch_id'],
//            'allocate_no' => $info['allocate_no'],
//        ])->update(['is_cancel' => 1]);

        return true;
    }

    /**
     * 序列号调入撤销
     * @param $info
     * 2022/9/30 16:07
     * Author: Sun Wu
     * @return bool
     */
    static protected function cancelSerialAllocateIn($info)
    {
        $instorageInfo = StorageManageModel::where('id', $info['curr_storage_manage_id'])->first();

        if($instorageInfo['delete_flag']) {
            throw new Exception('调入库存信息不存在，无法撤销,请查验后重试');
        }

        if($instorageInfo['in_storage_num'] < 1) {
            throw new Exception('调入后的库存数量不足，无法撤销,请查验后重试');
        }

        $serialNo = array_filter(explode(',', $info['serial_number']), function($v) { return $v !== ''; });
        $instorageSerialInfo = SerialNumberModel::where([
            'storage_manage_id' => $info['curr_storage_manage_id']
        ])
            ->whereIn('serial_no', $serialNo)
            ->get()->toArray();

        $serialInfo = [];
        foreach($instorageSerialInfo as $val) {
            if(!$val['status']) {
                throw new Exception('序列号:'.$val['serial_no'].'已被使用，无法撤销');
            }

            $serialInfo[] = [
                'id' => $val['id'],
                'storage_manage_id' => $info['last_storage_manage_id']
            ];
        }

        if(!empty($serialInfo)) {
            batch()->update(new SerialNumberModel, $serialInfo, 'id');
        }

        $instorageInfo->in_storage_num = $instorageInfo->in_storage_num - $info['operate_num'];
        $instorageInfo->virtual_storage_num = $instorageInfo->virtual_storage_num - $info['operate_num'];
        $instorageInfo->save();

//        $instorageSerialInfo->storage_manage_id = $info['last_storage_manage_id'];
//        $instorageSerialInfo->save();

        StorageManageModel::where('id', $info['last_storage_manage_id'])
            ->update([
                'in_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'virtual_storage_num' => DB::raw('virtual_storage_num + '.$info['operate_num']),
                'delete_flag' => 0
            ]);

        $inBatchInfo = StorageBatchModel::where('id', $info['batch_id'])->first();

        if(!empty($inBatchInfo)) {
            //撤销调入产生的批次信息
            if($inBatchInfo['batch_left_num'] > 0) {
                $inBatchInfo->batch_left_num = $inBatchInfo->batch_left_num - $info['operate_num'];
                $inBatchInfo->save();
            }
            else {
                //调入产生的批次信息数量不足，找到批次数量最大的批次抵扣一次
                $findInbatchInfo = StorageBatchModel::where('storage_manage_id', $info['curr_storage_manage_id'])
                    ->orderBy('batch_left_num', 'desc')
                    ->first();

                if($findInbatchInfo['batch_left_num'] > 0) {
                    $findInbatchInfo->batch_num = $findInbatchInfo->batch_num - $info['operate_num'];
                    $findInbatchInfo->batch_left_num = $findInbatchInfo->batch_left_num - $info['operate_num'];
                    $findInbatchInfo->save();
                }
                else {
                    //以上条件未满足时，将调入的批次删除
                    $inBatchInfo->delete_flag = 1;
                    $inBatchInfo->save();
                }
            }
        }
//
//        LogOutStorageModel::where([
//            'type' => 1,
//            'curr_storage_manage_id' => $info['last_storage_manage_id'],
//            'next_storage_manage_id' => $info['curr_storage_manage_id'],
//            'serial_number' => $info['serial_number'],
//            'allocate_no' => $info['allocate_no'],
//        ])->update(['is_cancel' => 1]);

        return true;
    }

    //撤销直接入库
    static public function cancelDirectInstorage($data)
    {
        $logInstorageInfo = LogInstorageModel::where([
            'id' => $data['id'],
            'main_id' => $data['main_id']
        ])->first();

        if(empty($logInstorageInfo)) {
            return ['code' => 1, 'msg' => '无效操作记录', 'data' => ''];
        }

        if($logInstorageInfo['type'] != 2) {
            return ['code' => 1, 'msg' => '非直接入库，无法完成撤销', 'data' => ''];
        }

//        if($logInstorageInfo['is_cancel'] == 1) {
//            return ['code' => 1, 'msg' => '已撤销，无法重复操作', 'data' => ''];
//        }

        $storageManageInfo = StorageManageModel::where([
            'id' => $logInstorageInfo['curr_storage_manage_id'],
            'delete_flag' => 0
        ])->first();

        $storageBatchInfo = [];

        if(!empty($logInstorageInfo['batch_id'])){

            $storageBatchInfo = StorageBatchModel::where('id',$logInstorageInfo['batch_id'])->first();

        }

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '记录中商品已被删除，无法完成撤销', 'data' => ''];
        }

//        if($logInstorageInfo['operate_num'] > $storageManageInfo['in_storage_num']) {
//            return ['code' => 1, 'msg' => '当前商品库存数不足(实际库存:'.$storageManageInfo['in_storage_num'].',撤销数量:'.$logInstorageInfo['operate_num'].')，无法完成撤销', 'data' => ''];
//        }
//
//        if($storageManageInfo['virtual_storage_num'] > 0) {
//            if($logInstorageInfo['operate_num'] > $storageManageInfo['virtual_storage_num']) {
//                return ['code' => 1, 'msg' => '当前商品虚拟库存数不足(实际库存:'.$storageManageInfo['virtual_storage_num'].',撤销数量:'.$logInstorageInfo['operate_num'].')，无法完成撤销', 'data' => ''];
//            }
//        }

        DB::beginTransaction();

        try {
            LogInstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);
            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $logInstorageInfo['curr_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$logInstorageInfo['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$logInstorageInfo['operate_num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $logInstorageInfo['curr_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$logInstorageInfo['operate_num']),
                    ]);
            }
            if(!empty($logInstorageInfo['batch_id']) && !empty($storageBatchInfo)){

                if($logInstorageInfo['operate_num'] <= $storageBatchInfo['batch_left_num']) {

                    $num = $storageBatchInfo['batch_left_num']- $logInstorageInfo['operate_num'];

                    StorageBatchModel::where('id',$logInstorageInfo['batch_id'])->update(['batch_left_num' => $num]);
                }
            }

            if(!empty($logInstorageInfo['serial_number'])){
                $scondition = [];
                $serialNumberList = explode(',', $logInstorageInfo['serial_number']);

                $scondition['goods_id'] = $logInstorageInfo['materiel_type_id'];
                $scondition['storage_manage_id'] = $logInstorageInfo['curr_storage_manage_id'];
//                $scondition['main_id'] = $logInstorageInfo['main_id'];
                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->delete();
//                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status' => 0]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (Exception $e) {
            DB::rollBack();
            Log::debug('撤销直接入库:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //撤销-直接出库
    static public function cancelDirectOutstorage($data)
    {
        $logInfo = LogOutstorageModel::where('id', $data['id'])->first();

        if($logInfo['type'] != 2) {
            return ['code' => 1, 'msg' => '非直接出库，无法完成撤销', 'data' => 0];
        }

        if($logInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        $storageBatchInfo = [];

        if(!empty($logInfo['storage_batch_id'])){

            $storageBatchInfo = StorageBatchModel::where('id',$logInfo['storage_batch_id'])->first();

        }

        DB::beginTransaction();

        try {
            StorageManageModel::where('id', $logInfo['curr_storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num + '.$logInfo['operate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num + '.$logInfo['operate_num']),
                    'delete_flag' => 0
                ]);

            LogOutstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);

            if(!empty($logInfo['storage_batch_id']) && !empty($storageBatchInfo)){

                $num = $storageBatchInfo['batch_left_num']+ $logInfo['operate_num'];

                StorageBatchModel::where('id',$logInfo['storage_batch_id'])->update(['batch_left_num' => $num]);
            }

            if(!empty($logInfo['serial_number'])){

                $serialNumberList = explode(',', $logInfo['serial_number']);
                $scondition['goods_id'] = $logInfo['materiel_type_id'];


                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>1]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (Exception $e) {
            DB::rollBack();
            Log::debug('撤销-直接出库:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //撤销套餐出库
    static public function cancelPackage($data)
    {
        $packageInfo = LogPackageModel::where('id', $data['id'])->first();

        if($packageInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        $packageContentInfo = LogPackageContentModel::where('log_package_id', $data['id'])->get()->toArray();
        DB::beginTransaction();

        try {
            foreach($packageContentInfo as $value) {
                $result = StorageManageModel::where('id', $value['out_storage_manage_id'])->first();

                StorageManageModel::where('id', $value['out_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$value['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['operate_num']),
                        'delete_flag' => 0
                    ]);

                if($value['storage_batch_id'] != 0) {
                    StorageBatchModel::where('id', $value['storage_batch_id'])
                        ->increment('batch_left_num', $value['operate_num']);
                }

                if(!empty($value['serial_number'])){

                    $serialNumberList = explode(',', $value['serial_number']);
                    $scondition['status'] = 0;
                    $scondition['goods_id'] = $value['materiel_type_id'];


                    SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>1]);
                }
            }

            LogPackageModel::where('id', $data['id'])->update(['is_cancel' => 1]);
            LogOutPackageModel::where(['all_id_type' => 3, 'all_id' => $data['id']])->update(['is_cancel' => 1]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('撤销-套餐出库:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * 获取旧操作记录列表
     * @param $startTime
     * @param $startTime
     * @param $endTime
     * @param $userType
     * @param $userId
     * @param $mainId
     * @return array
     * @author ソンブ
     * @created_at: 2022/2/9 15:31
     */
    static public function oldLogList($type, $startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        switch($type) {
            case 0:
                $result = self::getOldInLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId);
                break;
            case 1:
                $result = self::getOldOutLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId);
                break;
        }

        return ['code' => 0, 'msg' => 'success', 'data' => $result];
    }

    static public function getOldInLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        if($userId == $mainId) {
            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('admin as g', 'g.id', '=', 'a.main_id')
                ->where('a.main_id', $mainId);
        }
        else {
            $userInfo = UserModel::where('new_id', $userId)->first();

            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('user as g', 'g.id', '=', 'a.oprater_id')
                ->where('a.oprater_id', $userInfo['id']);
        }

        if(!empty($startTime)) {
            $startTimeArr = explode(' ', $startTime);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($endTime)) {
            $endTimeArr = explode(' ', $endTime);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query = $query->whereBetween('a.oprate_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query = $query->where('a.oprate_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query = $query->where('a.oprate_time', '<=', $endTime);
        }

        $query = $query->whereIn('type', [0,1,6])
            ->orderBy('a.id', 'desc')
            ->paginate($pageSize,['*'], '',$currPage);

        foreach($query as $key => $value) {
            $query[$key]['oprate_time'] = date('Y-m-d H:i:s', $value['oprate_time']);
        }

        return $query;
    }

    static public function getOldOutLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        if($userId == $mainId) {
            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
                'h.package_name'
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('admin as g', 'g.id', '=', 'a.main_id')
                ->leftJoin('package as h', 'h.id', '=', 'a.package_id')
                ->where('a.main_id', $mainId);
        }
        else {
            $userInfo = UserModel::where('new_id', $userId)->first();

            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
                'h.package_name'
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('user as g', 'g.id', '=', 'a.oprater_id')
                ->leftJoin('package as h', 'h.id', '=', 'a.package_id')
                ->where('a.oprater_id', $userInfo['id']);
        }

        if(!empty($startTime)) {
            $startTimeArr = explode(' ', $startTime);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($endTime)) {
            $endTimeArr = explode(' ', $endTime);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query = $query->whereBetween('a.oprate_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query = $query->where('a.oprate_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query = $query->where('a.oprate_time', '<=', $endTime);
        }

        $query = $query->whereIn('type', [2,3])
            ->orderBy('a.id', 'desc')
            ->paginate($pageSize,['*'], '',$currPage);

        foreach($query as $key => $value) {
            $query[$key]['package_name'] = empty($value['package_name'])?'':$value['package_name'];
            $query[$key]['oprate_time'] = date('Y-m-d H:i:s', $value['oprate_time']);
        }

        return $query;
    }

    static public function cancelOldLog($id, $userId, $mainId)
    {
        $logInfo = InStorageLogModel::where('id', $id)->first();

        if($logInfo['is_cancel']) {
            return ['code' => 1, 'msg' => '已撤销，无法重复操作', 'data' => ""];
        }

        $storageManageInfo = StorageManageModel::where('id', $logInfo['storage_id'])->where('delete_flag', 0)->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存信息不存在，无法完成撤销', 'data' => ""];
        }

        //入库撤销
        if(in_array($logInfo['type'], [0,1,6])) {
            $result = self::cancelOldIn($logInfo, $storageManageInfo);
        }
        //出库撤销
        else {
            $result = self::cancelOldOut($logInfo, $storageManageInfo);
        }

        return $result;
    }

    //旧操作记录撤销
    static public function cancelOldIn($logInfo, $storageManageInfo)
    {
        DB::beginTransaction();

        try {
            if($logInfo['oprate_num'] > $storageManageInfo['in_storage_num']) {
                return ['code' => 1, 'msg' => '库存不足，无法撤销', 'data' => ""];
            }

            if($logInfo['type'] == 6) {
                StorageManageModel::where('id', $logInfo['before_change_storage'])->increment('in_storage_num', $logInfo['oprate_num'], [
                    'delete_flag' => 0
                ]);
            }

            StorageManageModel::where('id', $storageManageInfo['id'])->decrement('in_storage_num', $logInfo['oprate_num']);
            InStorageLogModel::where('id', $logInfo['id'])->update(['is_cancel' => 1]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('旧操作记录入库撤销:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '撤销失败，请联系管理员', 'data' => ""];
        }
    }

    static public function cancelOldOut($logInfo, $storageManageInfo)
    {
        DB::beginTransaction();

        try {
            StorageManageModel::where('id', $storageManageInfo['id'])->increment('in_storage_num', $logInfo['oprate_num'], [
                'delete_flag' => 0
            ]);
            InStorageLogModel::where('id', $logInfo['id'])->update(['is_cancel' => 1]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('旧操作记录出库库撤销:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '撤销失败，请联系管理员', 'data' => ""];
        }
    }

    public static function inLogExport(array $data, array $user)
    {
        $startTime = empty($data['start_time'])?'':strtotime($data['start_time']);
        $endTime = empty($data['end_time'])?'':strtotime($data['end_time']);

        return LogInStorageModel::inLogExport($data, $user, $startTime, $endTime);
    }

    public static function outLogExport(array $data, array $user)
    {
        $startTime = empty($data['start_time'])?'':strtotime($data['start_time']);
        $endTime = empty($data['end_time'])?'':strtotime($data['end_time']);

        return LogOutStorageModel::outLogExport($data, $user, $startTime, $endTime);
    }

    public static function packageOutLogExport($packageId)
    {
        $logData = LogPackageModel::outLogExport($packageId);

        $result = [];
        $materielLine = [];
        foreach($logData as $key => $value) {
            $materielLine[] = count($value['has_many_content']);
            foreach($value['has_many_content'] as $val) {
                $result[] = [
                    'package_name' => $value['package_name'],
                    'num' => $value['num'],
                    'nickname' => $value['nickname'],
                    'remark' => empty($value['remark'])?'':$value['remark'],
                    'out_storage_time' => $value['out_storage_time'],
                    'created_at' => $value['created_at'],
                    'storage_name' => $val['storage_name'],
                    'storage_address' => $val['storage_address'],
                    'materiel_name' => $val['materiel_name'],
                    'type_name' => $val['type_name'],
                    'materiel_img' => $val['materiel_img'],
                    'operate_num' => $val['operate_num'],
                    'last_storage_num' => $val['last_storage_num'],
                    'next_storage_num' => $val['next_storage_num'],
                    'shelf_name' => $val['shelf_name'],
                    'location_name' => $val['location_name'],
                    'batch_no' => $val['batch_no'],
                ];
            }
        }

        return ['data1' => $result, 'data2' => $materielLine];
    }

    static public function getPackageId($data, $user)
    {
        $startTime = empty($data['start_time'])?'':strtotime($data['start_time']);
        $endTime = empty($data['end_time'])?'':strtotime($data['end_time']);
        $keyword = empty($data['keyword'])?'':$data['keyword'];

        $query = LogPackageModel::select(
            'a.id',
        )
            ->from('log_package as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->leftJoin('log_package_content as c', 'c.log_package_id', '=', 'a.id')
            ->leftJoin('storage_shelf_location as d','d.id','=','c.location_id')
            ->leftJoin('storage_shelf as e','e.id','=','c.shelf_id')
            ->where('a.delete_flag', 0)
            ->where($user)
            ->where('a.is_cancel', $data['status']);

        if($data['materiel_class_id'] != 0) {
            $query->where('c.materiel_class_id', $data['materiel_class_id']);
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('a.created_at', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('a.created_at', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('a.created_at', '<=', $endTime);
        }

        $query->where(function($query) use ($keyword) {
            $query->orWhere('package_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_name', 'like', '%'.$keyword.'%');
            $query->orWhere('type_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_no', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_class_no', 'like', '%'.$keyword.'%');
        });

        return $query->get()->toArray();
    }
}
